package com.csj.mvvm.utils

import android.text.TextUtils
import java.math.BigDecimal
import java.text.DecimalFormat

/**
 * 高精度计算
 */
object ArithUtil {

    /**
     * 精确加法
     */
    fun add(value1: Double, value2: Double): Double {
        val b1: BigDecimal = BigDecimal.valueOf(value1)
        val b2: BigDecimal = BigDecimal.valueOf(value2)
        return b1.add(b2).toDouble()
    }

    /**
     * 精确减法
     */
    fun sub(value1: Double, value2: Double): Double {
        val b1: BigDecimal = BigDecimal.valueOf(value1)
        val b2: BigDecimal = BigDecimal.valueOf(value2)
        return b1.subtract(b2).toDouble()
    }

    /**
     * 精确乘法
     */
    fun mul(value1: Double, value2: Double): Double {
        val b1: BigDecimal = BigDecimal.valueOf(value1)
        val b2: BigDecimal = BigDecimal.valueOf(value2)
        return b1.multiply(b2).toDouble()
    }

    /**
     * 精确乘法
     */
    fun mul(value1: Double, value2: Double, scale: Int): Double {
        val b1: BigDecimal = BigDecimal.valueOf(value1)
        val b2: BigDecimal = BigDecimal.valueOf(value2)
        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_DOWN).toDouble()
    }

    /**
     * 精确除法 使用默认精度
     */
    @Throws(IllegalAccessException::class)
    fun div(value1: Double, value2: Double): Double {
        return div(value1, value2, 10)
    }

    /**
     * 精确除法【四舍五入】
     *
     * @param scale 精度
     */
    @Throws(IllegalAccessException::class)
    fun div(value1: Double, value2: Double, scale: Int): Double {
        if (scale < 0) {
            throw IllegalAccessException("精确度不能小于0")
        }
        val b1: BigDecimal = BigDecimal.valueOf(value1)
        val b2: BigDecimal = BigDecimal.valueOf(value2)
        // return b1.divide(b2, scale).toDouble();
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toDouble()
    }

    /**
     * 四舍五入
     *
     * @param scale 小数点后保留几位
     */
    @Throws(IllegalAccessException::class)
    fun round(v: Double, scale: Int): Double {
        return div(v, 1.0, scale)
    }

    /**
     * 保留 n 位小数，直接删除多余小数位
     *
     * @param v
     * @param scale 小数点后保留几位
     * @return
     * @throws IllegalAccessException
     */
    @Throws(IllegalAccessException::class)
    fun roundDown(v: Double, scale: Int): Double {
        if (scale < 0) {
            throw IllegalAccessException("精确度不能小于0")
        }
        val b1: BigDecimal = BigDecimal.valueOf(v)
        val b2: BigDecimal = BigDecimal.valueOf(1)
        return b1.divide(b2, scale, BigDecimal.ROUND_DOWN).toDouble()
    }

    /**
     * 比较
     */
    fun equalTo(b1: BigDecimal?, b2: BigDecimal?): Boolean {
        return if (b1 == null || b2 == null) {
            false
        } else 0 == b1.compareTo(b2)
    }

    /**
     * @param d 需要格式化的值
     * @Desc 格式化
     * @Time 2019/7/3 11:08
     */
    fun format(d: Double): String? {
        return format(d, 0)
    }

    /**
     * @param d     需要格式化的值
     * @param scale 小数位
     * @Desc 格式化
     * @Time 2019/7/3 11:08
     */
    fun format(d: Double, scale: Int): String? {
        val sb = StringBuilder("0")
        for (i in 0 until scale) {
            if (i == 0) {
                sb.append(".").append("0")
            } else {
                sb.append("0")
            }
        }
        val format = DecimalFormat(sb.toString())
        return format.format(d)
    }

    //格式 ###,###.##
    //point 几位小数填几个0
    fun getComFormat(data: String?, point: String): String? {
        if (TextUtils.isEmpty(data) || TextUtils.isEmpty(point)) {
            return ""
        }
        val value = BigDecimal(data)
        if (value.toString() == "") {
            return ""
        }
        return if (value.toDouble() == 0.0) {
            "0"
        } else getFormat(",###.$point", value)
    }

    fun getNumFormat(data: String?, point: String): String? {
        if (TextUtils.isEmpty(data) || TextUtils.isEmpty(point)) {
            return ""
        }
        val value = BigDecimal(data)
        if (value.toString() == "") {
            return ""
        }
        return if (value.toDouble() == 0.0) {
            "0"
        } else getFormat("0.$point", value)
    }

    private fun getFormat(style: String, value: BigDecimal): String? {
        val df = DecimalFormat()
        df.applyPattern(style) // 将格式应用于格式化器
        return df.format(value.toDouble())
    }
}